﻿#include "StdAfx.h"
#include <afxmt.h>
#include "GPSParser.h"
#include "StringTokenizer.h"
#include <cmath>

CGPSParser::CGPSParser(void)
{
	AtBeginClass();
}

CGPSParser::~CGPSParser(void)
{
	AtEndClass();
}

int CGPSParser::AtBeginClass(void)
{
	return 0;
}

int CGPSParser::AtEndClass(void)
{
	m_vecGPGGA.clear();
	m_vecPAVT.clear();
	return 0;
}

int CGPSParser::GetTimeValue( char *pchData)
{
	int fTValue = atof( pchData );
	int fFirst = int(fTValue/10000);	// 첫번째 값.	14...
	int fSecond = (fTValue - fFirst*10000)/100;	// 두번째 값.	43....
	int fThird = (fTValue - fFirst*10000) - fSecond* 100;		// 세번째 값.	

	return fFirst * 3600 + fSecond * 60 + fThird;
}

void CGPSParser::ReadLineFile(CString szFileName)
{
	CStdioFile  file;
	CString strBufferLine;
	string strTime;
	int nTValue = 0;
	string szRetLat, szRetLong; 

	USES_CONVERSION;

	if(!file.Open(szFileName, CFile::modeRead | CFile::shareDenyNone ))	return;

	while(file.ReadString( strBufferLine)) //한줄씩 읽기
	{
		if( strBufferLine.GetLength() < 5 &&  file.GetPosition() != file.GetLength() )	continue;

		CStringTokenizer<CStringArray> strTokArray;	// declafre a tokenizer class derived from CStringArray
		strTokArray.RemoveOptions(CStringTokenizer<CStringArray>::IGNORE_EMPTY_TOKENS);	// Don't ignore the empty tokens.  By default, they are ignored.
		UINT iStartOffset = strTokArray.Tokenize(strBufferLine, _T(",*"), _T("\n"), 0);		// tokenize words in the 1st line
		if( !CheckSumData( W2A(strBufferLine.GetBuffer(0)), W2A(strTokArray[strTokArray.GetSize() -1].GetBuffer(0))) )	 continue;

		if( strTokArray.GetSize() > 0 )
		{
			if( !strTokArray[0].Compare(_T("$GPGGA")) )
			{
				CGPSData_GPGGA GpggaObj;

				strTime = GpggaObj.strTime = W2A(strTokArray[1]);
				nTValue = GetTimeValue((char*)strTime.c_str());
				//printf("\n Time:[%d]", nTValue );
				GpggaObj.nTime = nTValue;

				GpggaObj.strLong = W2A(strTokArray[2]);
				GpggaObj.strLat = W2A(strTokArray[4]);

				szRetLat, szRetLong;
				ChangeMNEALatLong( W2A(strTokArray[4]), W2A(strTokArray[2]), szRetLat, szRetLong );

				//printf(" Lat:[%s]  Long:[%s]", GpggaObj.strLat.c_str(), GpggaObj.strLong.c_str() );

				GpggaObj.strLat2 = szRetLat;
				GpggaObj.strLong2 = szRetLong;

				GpggaObj.strVelMiles = "0.00000";
				GpggaObj.strVelocity = "0.00000";

				m_vecGPGGA.push_back( GpggaObj );
			}
			else if( !strTokArray[0].Compare(_T("$PAVT")) )		
			{
				CGPSData_PAVT PavtObj;

				PavtObj.strTime = strTime;
				PavtObj.nTime = nTValue;
				PavtObj.strAcelX = W2A(strTokArray[1]);
				PavtObj.strAcelY = W2A(strTokArray[2]);
				PavtObj.strAcelZ = W2A(strTokArray[4]);

				PavtObj.strMovX = W2A(strTokArray[1]);
				PavtObj.strMovY = W2A(strTokArray[2]);
				PavtObj.strMovZ = W2A(strTokArray[4]);
				m_vecPAVT.push_back( PavtObj );
			}
			else if( !strTokArray[0].Compare(_T("$GPVTG")) )		
			{
				int nSize = m_vecGPGGA.size();
				if( nSize > 0 )
				{
					float fMiles = conv_km2mile(atof(W2A(strTokArray[7])));
					char chMiles[20] = {0,};
					sprintf( chMiles, "%f", fMiles );
					m_vecGPGGA[m_vecGPGGA.size()-1].strVelMiles = chMiles;
					m_vecGPGGA[m_vecGPGGA.size()-1].strVelocity = W2A(strTokArray[7]);
				}
			}
		}
	}
}

void CGPSParser::DisplayData()
{
	TRACE("\n----------------------------------------------------------------------------------------");
	for( int i=0; i< m_vecGPGGA.size(); i++ )
	{
		TRACE("\n-->>[%s][%s][%s]",m_vecGPGGA[i].strTime.c_str(), 
			m_vecGPGGA[i].strLong.c_str(), 
			m_vecGPGGA[i].strLat.c_str());

		int nIndex = GetPAVTIndex( (char *)m_vecGPGGA[i].strTime.c_str() );
		if( nIndex != -1 )
		{
			TRACE("\n-->>[%s][%s][%s][%s]",m_vecPAVT[nIndex].strTime.c_str(),
				m_vecPAVT[nIndex].strAcelX.c_str(), 
				m_vecPAVT[nIndex].strAcelY.c_str(), 
				m_vecPAVT[nIndex].strAcelZ.c_str());
		}
	}
}

int CGPSParser::GetPAVTIndex( char *pchTime )
{
	for( int i=0; i< m_vecPAVT.size(); i++ )
	{
		if( !m_vecPAVT[i].strTime.compare( pchTime ) )
			return i;
	}
	return -1;
}

BOOL  CGPSParser::CheckSumData( char *nmea_line, char *pChChecksum )
{
	char chData[2] = {0,};
	char *xor_chars = "0123456789ABCDEF";
	int chcount = 1, len_nmea;
	int xor = 0;

	len_nmea = strlen(nmea_line);
	while ( (chcount < len_nmea) && ( nmea_line[chcount] != '*') )
		xor ^= (unsigned short int)(nmea_line[chcount++]);

	if ( nmea_line[chcount] != '*' ) return FALSE;
	if( (*(pChChecksum) == xor_chars[xor >> 4] ) && (*(pChChecksum +1) == xor_chars[xor & 0x0F]) )	return TRUE;
	return FALSE;
}

void CGPSParser::GetDoMinSec( double dInputValue, double &dDo, double &dMin, double &dSec )
{
	dDo = int(dInputValue);
	dMin = (dInputValue - dDo) * 60.0f;
	dSec = (dMin - int(dMin)) * 60.0f;
	dMin = int(dMin);
}

double CGPSParser::GetDistance(double dLat01, double dLong01, double dLat02, double dLong02 )
{
	double dLong_Do[3], dLong_Min[3], dLong_Sec[3];
	double dLat_Do[3], dLat_Min[3], dLat_Sec[3];

	GetDoMinSec( dLong01, dLong_Do[0], dLong_Min[0], dLong_Sec[0] );
	GetDoMinSec( dLong02, dLong_Do[1], dLong_Min[1], dLong_Sec[1] );

	GetDoMinSec( dLat01, dLat_Do[0], dLat_Min[0], dLat_Sec[0] );
	GetDoMinSec( dLat02, dLat_Do[1], dLat_Min[1], dLat_Sec[1] );

	dLong_Do[2] = dLong_Do[1] - dLong_Do[0];
	dLong_Min[2] = dLong_Min[1] - dLong_Min[0];
	dLong_Sec[2] = dLong_Sec[1] - dLong_Sec[0];

	dLat_Do[2] = dLat_Do[1] - dLat_Do[0];
	dLat_Min[2] = dLat_Min[1] - dLat_Min[0];
	dLat_Sec[2] = dLat_Sec[1] - dLat_Sec[0];

	double distance_Lat = dLat_Do[2] *111 + dLat_Min[2] * 1.85 + dLat_Sec[2] * 0.031;
	double distance_Long = dLong_Do[2] *88.8 + dLong_Min[2] * 1.48 + dLong_Sec[2] * 0.025;

	double distanceResult = pow(pow( distance_Lat, 2.0) + pow( distance_Long, 2.0 ) , 1.0/2.0 );

	return distanceResult;
}

double CGPSParser::GetDoMinSecGPGGA( double dInputValue, double &dDo, double &dMin, double &dSec )
{
	dDo = int(dInputValue/100);
	dMin = dInputValue - dDo*100;
	dSec = 0.0f;
	return 0.0f;
}

double CGPSParser::GetDistanceOther(double dLat01, double dLong01, double dLat02, double dLong02 )
{
	double dLong_Do[3], dLong_Min[3], dLong_Sec[3];
	double dLat_Do[3], dLat_Min[3], dLat_Sec[3];
	
	GetDoMinSecGPGGA( dLat01, dLat_Do[0], dLat_Min[0], dLat_Sec[0] );
	GetDoMinSecGPGGA( dLat02, dLat_Do[1], dLat_Min[1], dLat_Sec[1] );

	GetDoMinSecGPGGA( dLong01, dLong_Do[0], dLong_Min[0], dLong_Sec[0] );
	GetDoMinSecGPGGA( dLong02, dLong_Do[1], dLong_Min[1], dLong_Sec[1] );

	dLong_Do[2] = dLong_Do[1] - dLong_Do[0];
	dLong_Min[2] = dLong_Min[1] - dLong_Min[0];
	dLong_Sec[2] = dLong_Sec[1] - dLong_Sec[0];

	dLat_Do[2] = dLat_Do[1] - dLat_Do[0];
	dLat_Min[2] = dLat_Min[1] - dLat_Min[0];
	dLat_Sec[2] = dLat_Sec[1] - dLat_Sec[0];

	double distance_Lat = dLat_Do[2] *111 + dLat_Min[2] * 1.85 + dLat_Sec[2] * 0.031;
	double distance_Long = dLong_Do[2] *88.8 + dLong_Min[2] * 1.48 + dLong_Sec[2] * 0.025;

	double distanceResult = pow(pow( distance_Lat, 2.0) + pow( distance_Long, 2.0 ) , 1.0/2.0 );
	TRACE("\n In Other Distance :[%f][%f][%f][%f]-[%f]", dLat01, dLong01, dLat02, dLong02, distanceResult );

	return distanceResult;
}

void CGPSParser::CalVelocity()
{
	char chData[100] ={0,};
	int nCount = GetAllCount();

	// 속도 : 시속 1km 는 초당 0.27 m 임.
	for( int i=0; i<nCount; i++ )
	{
		if( i < nCount-1 )
		{
			// 거리
			double dDistance = GetDistanceOther( atof(m_vecGPGGA[i].strLong.c_str()), atof(m_vecGPGGA[i].strLat.c_str()),
				atof(m_vecGPGGA[i+1].strLong.c_str()), atof(m_vecGPGGA[i+1].strLat.c_str()));

			// 속도 km
			sprintf(chData, "%f", GetVelocity( dDistance*1000, abs(atof(m_vecGPGGA[i].strTime.c_str()) - atof(m_vecGPGGA[i+1].strTime.c_str()))));
			m_vecGPGGA[i+1].strVelocity = chData;
			
			sprintf(chData,"%f", conv_km2mile(atof(chData)));
			m_vecGPGGA[i+1].strVelocity = chData;
		}
	}
}

void CGPSParser::ChangeMNEALatLong( string _szLat, string _szLong, string &_szRetLat, string &_szRetLong )
{
	char chDataLat[50] = {0,}, chDataLong[50] = {0,};
	float fLat = atof(_szLat.c_str()), fLong = atof(_szLong.c_str());
	float fLatRet = int(fLat/100), fLongRet = int(fLong/100);
	float fLatResult = fLatRet + (fLat - (fLatRet * 100))/60.0f;
	float fLongResult = fLongRet + (fLong - (fLongRet *100))/60.0f;

	sprintf( chDataLat, "%f", fLatResult );
	sprintf( chDataLong, "%f", fLongResult );
	_szRetLat = chDataLat;
	_szRetLong = chDataLong;
}

void CGPSParser::GetCurrentPos( int nIndex, string &szLat, string &szLong)
{
	if( m_vecGPGGA.size() > nIndex )
	{
		szLat = m_vecGPGGA[nIndex].strLat2;
		szLong = m_vecGPGGA[nIndex].strLong2;
	}
}

void CGPSParser::GetCurrentPos_Org( int nIndex, string &szLat, string &szLong)
{
	if( m_vecGPGGA.size() > nIndex )
	{
		szLat = m_vecGPGGA[nIndex].strLat;
		szLong = m_vecGPGGA[nIndex].strLong;
	}
} 

void CGPSParser::GetSpeed( int nIndex, string &szSpeed_Miles, string &szSpeed_Km )
{
	if( m_vecGPGGA.size() > nIndex )
	{
		szSpeed_Miles = m_vecGPGGA[nIndex].strVelMiles;
		szSpeed_Km = m_vecGPGGA[nIndex].strVelocity;
	}
	else
	{
		szSpeed_Miles = "0";
		szSpeed_Km = "0";
	}
}
